home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 November: Tool Chest / Dev.CD Nov 96 TC / Dev.CD Nov 96 TC.toast / Sample Code / Interapplication Communication / MenuScripter 4.0 / Sources / MSUtils.c < prev    next >
Encoding:
Text File  |  1996-07-09  |  15.0 KB  |  638 lines  |  [TEXT/CWIE]

  1. // MSUtils.c
  2. //
  3. // Original version by Jon Lansdell and Nigel Humphreys.
  4. // 4.0 and 3.1 updates by Greg Sutton.
  5. // ©Apple Computer Inc 1996, all rights reserved.
  6.  
  7. /*
  8.     Changes for 3.1:
  9.     
  10.         12-Oct-95    : CW : Simplified FeatureIsImplemented routine.
  11.                            Added init of gHasDragManager flag in CheckEnvironment.
  12.                            
  13.     Changes for 4.0:
  14.         17-Apr-96    : GS : Changed pascal calling conventions to C where possible.
  15.                            Changed behavior of outlining Up, Down and Other in Size menu.
  16.  
  17. */
  18.  
  19.  
  20. #ifdef THINK_C
  21.     #include "PLStrs.h"
  22. #else
  23.     #include <PLStringFuncs.h>
  24. #endif
  25. #include <Events.h>
  26. #include <Traps.h>
  27. #include <Dialogs.h>
  28. #include <Fonts.h>
  29. #include <Packages.h>
  30. #include <ToolUtils.h>
  31. #include <AppleEvents.h>
  32. #include <CodeFragments.h>
  33. #include "MSUtils.h"
  34.  
  35. //        Name:             LesserOf
  36. //        Purpose:        Returns the Lesser of two longints.
  37.  
  38. #pragma segment Utils
  39.         
  40. long    LesserOf( long A, long B )
  41. {
  42.     if ( A < B )
  43.         return( A );
  44.     else
  45.         return( B );
  46. } // LesserOf
  47.             
  48.  
  49. //        Name:             GreaterOf
  50. //        Purpose:        Returns the Greater of two longints.
  51.     
  52. #pragma segment Utils
  53.         
  54. long    GreaterOf( long A, long B )
  55. {
  56.     if ( A > B )
  57.         return(A);
  58.     else
  59.         return(B);
  60. } // GreaterOf
  61.             
  62.  
  63. //        Name:         ShowError
  64. //        Purpose:    Reports an error to the user as both string and number.
  65.  
  66. #pragma segment Utils
  67.         
  68. void    ShowError( Str255 theError, long theErrorCode )
  69. {
  70.     short     alertResult;
  71.     Str255    theString;
  72.     OSErr     myErr;
  73.      
  74.     myErr = AEInteractWithUser( kAEDefaultTimeout, nil, nil );
  75.      
  76.     if (myErr == noErr)
  77.     {
  78.         SetCursor(&qd.arrow);
  79.         NumToString(theErrorCode, theString);
  80.         ParamText( theError, theString, (unsigned char *)"", (unsigned char *)"" );
  81.         alertResult = Alert(300, nil);
  82.     }
  83. } // ShowError
  84.  
  85.  
  86. //        Name:             Ours
  87. //        Purpose:        Checks the frontmost window belongs to the app.
  88.  
  89. #pragma segment Utils        
  90.  
  91. Boolean    Ours( WindowPtr aWindow )
  92. {
  93.     if (aWindow)
  94.         if (((WindowPeek)aWindow)->windowKind == zoomDocProc)
  95.             return(true);
  96.  
  97.     return(false);
  98. } // Ours
  99.  
  100.  
  101. //        Name:             SetShortMenus
  102. //        Purpose:        Cuts the menus down to a minimum - Apple File Edit.
  103. //                        Greys out the unavailable options - used when no docs open
  104.  
  105. #pragma segment Utils        
  106.  
  107. void    SetShortMenus( void )
  108.     DeleteMenu(mfontID);
  109.     DeleteMenu(sizeID);
  110.     DeleteMenu(styleID);
  111.     DeleteMenu(mscriptID);
  112.     DeleteMenu(subroutineID);
  113.  
  114.     SetMenuItemState ( false, myMenus[fileM], fmClose);
  115.     SetMenuItemState ( false, myMenus[fileM], fmSave);
  116.     SetMenuItemState ( false, myMenus[fileM], fmSaveAs);
  117.     SetMenuItemState ( false, myMenus[fileM], fmRevert);
  118.     SetMenuItemState ( false, myMenus[fileM], fmPageSetUp);
  119.  
  120.     if (gGXIsPresent)
  121.     {
  122.         SetMenuItemState ( false, myMenus[fileM], fmPrint);
  123.         SetMenuItemState ( false, myMenus[fileM], fmPrintOne );
  124.     }
  125.     else
  126.         SetMenuItemState ( false, myMenus[fileM], fmNoGXPrint);
  127.  
  128.     // now the unnecessary items on the edit menu
  129.                 
  130.     SetMenuItemState ( false, myMenus[editM], undoCommand);
  131.     SetMenuItemState ( false, myMenus[editM], cutCommand);
  132.     SetMenuItemState ( false, myMenus[editM], copyCommand);
  133.     SetMenuItemState ( false, myMenus[editM], clearCommand);
  134.     SetMenuItemState ( false, myMenus[editM], pasteCommand);
  135.     SetMenuItemState ( false, myMenus[editM], selectAllCommand);
  136.  
  137.     DrawMenuBar();
  138. }  // SetShortMenus
  139.  
  140.  
  141. //        Name:         SetLongMenus
  142. //        Purpose:    Reinstates the full menu bar - called when first document
  143. //                     opened.
  144.  
  145. #pragma segment Utils        
  146.  
  147. void    SetLongMenus( void )
  148. {
  149.     InsertMenu(myMenus[fontM], 0);
  150.     InsertMenu(myMenus[sizeM], 0);
  151.     InsertMenu(myMenus[styleM], 0);
  152.     InsertMenu(myMenus[scriptM], 0);
  153.     InsertMenu(myMenus[subroutineM], 0);
  154.  
  155.     SetMenuItemState ( true, myMenus[fileM], fmClose);
  156.     SetMenuItemState ( true, myMenus[fileM], fmSave);
  157.     SetMenuItemState ( true, myMenus[fileM], fmSaveAs);
  158.     SetMenuItemState ( true, myMenus[fileM], fmRevert);
  159.     SetMenuItemState ( true, myMenus[fileM], fmPageSetUp);
  160.  
  161.     if (gGXIsPresent)
  162.     {
  163.         SetMenuItemState ( true, myMenus[fileM],  fmPrint );
  164.         SetMenuItemState ( true, myMenus[fileM],  fmPrintOne );
  165.     }
  166.     else
  167.         SetMenuItemState ( true, myMenus[fileM], fmNoGXPrint );
  168.  
  169.     // now the necessary items on the edit menu -
  170.     //    many other items fixed on each pass thru the main event
  171.     //    loop or before the window pulled down
  172.     
  173.     SetMenuItemState ( true, myMenus[editM], selectAllCommand);
  174.  
  175.     DrawMenuBar();
  176. }  // SetLongMenus
  177.  
  178.  
  179. //        Name:         SetStyleMenu
  180. //        Purpose:    Sets the style menu checking to reflect the style of the
  181. //                     first character of the current selection in the given
  182. //                     document.
  183.  
  184. #pragma segment Utils        
  185.         
  186. void    SetStyleMenu( DPtr theDoc )
  187. {
  188.     TextStyle    theTStyle;
  189.     short       contMode;
  190.     short       i;
  191.     
  192.     contMode = doFace;
  193.     
  194.     TEContinuousStyle(&contMode,&theTStyle,theDoc->theText);
  195.     
  196.     if ((contMode & doFace) != 0)
  197.     {
  198.         CheckItem(myMenus[styleM], cPlain,     (theTStyle.tsFace == 0));
  199.         CheckItem(myMenus[styleM], cBold,      (bold      & theTStyle.tsFace));
  200.         CheckItem(myMenus[styleM], cItalic,    (italic    & theTStyle.tsFace));
  201.         CheckItem(myMenus[styleM], cUnderline, (underline & theTStyle.tsFace));
  202.         CheckItem(myMenus[styleM], cOutline,   (outline   & theTStyle.tsFace));
  203.         CheckItem(myMenus[styleM], cShadow,    (shadow    & theTStyle.tsFace));
  204.         CheckItem(myMenus[styleM], cCondense,  (condense  & theTStyle.tsFace));
  205.         CheckItem(myMenus[styleM], cExtend,    (extend    & theTStyle.tsFace));
  206.     }
  207.     else
  208.         for (i=cPlain; i<= cExtend; i++)
  209.             CheckItem(myMenus[styleM], i, false);
  210. }
  211.  
  212.  
  213. //    Name:       SetSizeMenu
  214. //    Purpose:    Outline all the items if the current font is an
  215. //                outline font. Check the size of the current selection
  216.  
  217. #pragma segment Utils        
  218.  
  219. void    SetSizeMenu( DPtr theDoc )
  220. {
  221.     short         i;
  222.     short        aSize;
  223.     short        max;
  224.     long         theSize;
  225.     Str255        name;
  226.     Boolean       sizeinMenu;
  227.     Point         numer;
  228.     TextStyle    theStyle;
  229.     TEHandle    myText;
  230.     short       contMode;
  231.     
  232.     numer.h = 1;
  233.     numer.v = 1;
  234.     
  235.     myText = theDoc->theText;
  236.     
  237.     contMode = doSize+doFont;
  238.     
  239.     TEContinuousStyle( &contMode, &theStyle, theDoc->theText );
  240.     
  241.     sizeinMenu = false;
  242.     max = CountMItems(myMenus[sizeM]);
  243.     for (i = 1; i <= max - 5; i++)
  244.     {
  245.         GetItem(myMenus[sizeM], i, name);
  246.         StringToNum(name, &theSize);
  247.         aSize = (short)theSize;
  248.  
  249.         if (RealFont(theStyle.tsFont, aSize) && (contMode & doFont) != 0) // there is only one font and this size exists
  250.             SetItemStyle(myMenus[sizeM], i, outline);
  251.         else
  252.             SetItemStyle(myMenus[sizeM], i, 0);
  253.  
  254.         if ((aSize == theStyle.tsSize) && (contMode & doSize) != 0)
  255.         {
  256.             sizeinMenu = true;
  257.             CheckItem(myMenus[sizeM], i, true);
  258.         }
  259.         else
  260.             CheckItem(myMenus[sizeM], i, false);
  261.     }
  262.     
  263.     // If it's not a size in the menu,and there is only one size in the
  264.     //  selection range check the other item
  265.     
  266.     if (! sizeinMenu && (contMode & doSize) != 0)
  267.     {
  268.         CheckItem(myMenus[sizeM], max, true);
  269.  
  270.         if ( RealFont(theStyle.tsFont, theStyle.tsSize ) && (contMode & doFont) != 0 )
  271.             SetItemStyle(myMenus[sizeM], max, outline);
  272.         else
  273.             SetItemStyle(myMenus[sizeM], max, 0);
  274.     }
  275.     else
  276.     {
  277.         CheckItem(myMenus[sizeM], max, false);
  278.         SetItemStyle(myMenus[sizeM], max, 0);
  279.     }
  280.  
  281.         // Outline Up if next size up is available
  282.     if ( RealFont(theStyle.tsFont, theStyle.tsSize + 1 ) && (contMode & doFont) != 0 )
  283.         SetItemStyle(myMenus[sizeM], max - 3, outline);
  284.     else
  285.         SetItemStyle(myMenus[sizeM], max - 3, 0);
  286.  
  287.         // Outline Down if next size up is available
  288.     if ( RealFont(theStyle.tsFont, theStyle.tsSize - 1 ) && (contMode & doFont) != 0 )
  289.         SetItemStyle(myMenus[sizeM], max - 2, outline);
  290.     else
  291.         SetItemStyle(myMenus[sizeM], max - 2, 0);
  292. }
  293.  
  294.  
  295. //    Name:       SetFontMenu
  296. //    Purpose:    Set the font menu according to the state of
  297. //                                current selection of the supplied document.
  298.  
  299. #pragma segment Utils
  300.         
  301. void    SetFontMenu( DPtr theDoc )
  302. {
  303.     MenuHandle        theMHandle;
  304.     short            theNumber;
  305.     short            i;
  306.     short            max;
  307.     Str255            name;
  308.     TextStyle        theStyle;
  309.     short            contMode;
  310.     
  311.     theMHandle = GetMHandle(mfontID);
  312.     
  313.     if (gFontMItem)
  314.     CheckItem(theMHandle, gFontMItem, false);
  315.         
  316.     max = CountMItems(theMHandle);
  317.     
  318.     contMode = doFont;
  319.     TEContinuousStyle(&contMode,&theStyle,theDoc->theText);
  320.     
  321.     gFontMItem = 0;
  322.     
  323.     if (contMode & doFont)
  324.         for (i=1; i<=max; i++)
  325.         {
  326.             GetItem(theMHandle, i, name);
  327.             GetFNum(name, &theNumber);
  328.             if (theNumber == theStyle.tsFont)
  329.                 gFontMItem = i;
  330.         }
  331.     
  332.     if (gFontMItem)
  333.         CheckItem(theMHandle, gFontMItem, true);
  334.         
  335.     SetSizeMenu(theDoc);
  336.     SetStyleMenu(theDoc);
  337. }
  338.  
  339.  
  340. //    Name:       GetTempFileName
  341. //    Purpose:    Fills newstring with a temporary file name.
  342.  
  343. #pragma segment Utils
  344.  
  345. void    GetTempFileName( DPtr aDoc, Str255 newString )
  346. {
  347.     Str255        s;
  348.     Str255        fileName;
  349.     
  350.     if (aDoc->everSaved == false)
  351.         PLstrcpy(fileName, (unsigned char *)"\pTEXTra");
  352.     else
  353.         PLstrcpy(fileName, aDoc->theFileName);
  354.     
  355.     // generate a unique(ish) temporary filename
  356.     
  357.     if (fileName[0] > 21)
  358.       fileName[0] = 21;
  359.             
  360.     NumToString(TickCount(), s);
  361.     
  362.     PLstrcat(fileName, s);
  363.     
  364.     PLstrcpy(newString,fileName);
  365. }
  366.  
  367.  
  368. //    Name:       SetText
  369. //    Purpose:    Sets the text of the supplied itemNo in aDialog to 
  370. //                                theString and select it.
  371.  
  372. #pragma segment Utils
  373.  
  374. void    SetText( DialogPtr aDialog, short itemNo, Str255 theString )
  375. {
  376.     Handle      itemHandle;
  377.     Rect        box;
  378.     short       kind;
  379.     TEHandle    theTEHandle;
  380.     
  381.     GetDItem(aDialog, itemNo, &kind, &itemHandle, &box);
  382.     SetIText(itemHandle, theString);
  383.     
  384.     theTEHandle = ((DialogPeek)aDialog)->textH;
  385.     
  386.     // Set all the text to be selected
  387.     if (theTEHandle)
  388.         TESetSelect(0, 255, theTEHandle);
  389. }
  390.             
  391.  
  392. //    Name:       RetrieveText
  393. //    Purpose:    Returns the text of anItem in aDialog in aString.
  394.  
  395. #pragma segment Utils
  396.  
  397. void    RetrieveText( DialogPtr aDialog, short anItem, Str255 aString )
  398. {
  399.     short      kind;
  400.     Rect       box;
  401.     Handle     itemHandle;
  402.     
  403.     GetDItem(aDialog, anItem, &kind, &itemHandle, &box);
  404.     GetIText(itemHandle, aString);
  405. }
  406.  
  407.  
  408. //    Name:       DrawDefaultOutline
  409. //    Purpose:    Draws an outline around theItem.
  410. //                    Called as a useritem Proc by the dialog manager.
  411. //                    To use place a useritem over the default item in the
  412. //                    dialog and install the address of this proc as the item
  413. //                    handle.
  414.  
  415. #pragma segment Utils
  416.  
  417. pascal void    DrawDefaultOutline( DialogPtr theDialog, short theItem )
  418. {
  419.     short       kind;
  420.     Handle      itemHandle;
  421.     Rect        box;
  422.             
  423.     GetDItem(theDialog, theItem, &kind, &itemHandle, &box);
  424.     PenSize(3, 3);
  425.     InsetRect(&box, - 4, - 4);
  426.     FrameRoundRect(&box, 16, 16);
  427.     PenNormal();
  428. } // DrawDefaultOutline
  429.             
  430.  
  431. //    Name:       AdornDefaultButton
  432. //    Purpose:    Installs DrawDefaultOutline as the useritem proc
  433. //                    for the given item.
  434.  
  435. #pragma segment Utils
  436.         
  437. void    AdornDefaultButton(DialogPtr theDialog,short theItem)
  438. {
  439.     short       kind;
  440.     Handle      itemHandle;
  441.     Rect        box;
  442.     
  443.     GetDItem(theDialog, theItem, &kind, &itemHandle, &box);
  444.     SetDItem(theDialog, theItem, kind, (Handle)gDefaultButtonUPP, &box);
  445. }
  446.  
  447. void    GetRectOfDialogItem( DialogPtr theDialog, short theItem, Rect *theRect )
  448. {
  449.     short       kind;
  450.     Handle      itemHandle;
  451.     
  452.     GetDItem(theDialog, theItem, &kind, &itemHandle, theRect);
  453. }
  454.  
  455. // -------  Determining of Gestalt is available -------
  456. // The following routines come from the Inside Mac VI recommendations
  457. //  about how to find if a trap is available
  458.  
  459. //    The glue for Gestalt will be in MPW 3.2, so if it is available we will also
  460. //   need to check the system version
  461.  
  462. #pragma segment Utils
  463.  
  464. short    NumToolboxTraps(void)
  465. {
  466.     if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  467.         return(0x200);
  468.     else
  469.         return(0x400);
  470. }
  471.  
  472. #pragma segment Utils
  473.  
  474. #define TrapMask  0x0800
  475.  
  476. TrapType    GetTrapType(short theTrap)
  477. {
  478.     if ((theTrap & TrapMask) > 0)
  479.         return(ToolTrap);
  480.     else
  481.         return(OSTrap);
  482. }
  483.  
  484. #pragma segment Utils
  485.  
  486. Boolean    TrapAvailable(short theTrap)
  487. {
  488.     TrapType  tType;
  489.     
  490.     tType = GetTrapType(theTrap);
  491.     if (tType == ToolTrap)
  492.     {
  493.         theTrap = theTrap & 0x07FF;
  494.         if (theTrap >= NumToolboxTraps())
  495.             theTrap = _Unimplemented;
  496.     }
  497.  
  498.     return(NGetTrapAddress(theTrap, tType) != NGetTrapAddress(_Unimplemented,ToolTrap));
  499. }
  500.  
  501. #pragma segment Utils
  502.  
  503. #define _Gestalt 0xA1AD
  504.  
  505. Boolean    GestaltAvailable( void )
  506. {
  507.     return(TrapAvailable(_Gestalt));
  508. }
  509.  
  510.  
  511. // ------ FeatureIsImplemented ------
  512. // This is called to use Gestalt to determine if a feature is implemented.
  513. // This applies to only those referenced by OSType.
  514.  
  515. #pragma segment Utils
  516.  
  517. Boolean FeatureIsImplemented( OSType theFeature, short theTestBit )
  518. {
  519.     OSErr     err;
  520.     long      result;
  521.  
  522.     err = Gestalt ( theFeature, &result );
  523.     return (err == noErr && (result & (1L << theTestBit)));
  524. }
  525.  
  526.  
  527. #pragma segment Utils
  528.  
  529. Boolean    CheckEnvironment( void )
  530. {
  531.     long        response;
  532.  
  533.         // first determine of Gestalt is available- if it isn't exit
  534.         // as we only run under 7.0.  It could it present in 6.04 - so we need
  535.         // to do some further checks for important features
  536.     gGestaltAvailable = GestaltAvailable();
  537.     
  538.     if (!gGestaltAvailable)
  539.         return(false);
  540.  
  541.         // check if the Edition Manager is present
  542.     gEditionManagerImplemented = FeatureIsImplemented(gestaltEditionMgrAttr, gestaltEditionMgrPresent);
  543.  
  544.         // and for good measure - the Alias manager
  545.     gAliasManagerImplemented  = FeatureIsImplemented(gestaltAliasMgrAttr, gestaltAliasMgrPresent);
  546.  
  547.         // check for the AppleEvents manager - we certainly can't work without it
  548.     gAppleEventsImplemented   = FeatureIsImplemented(gestaltAppleEventsAttr, gestaltAppleEventsPresent);
  549.  
  550.         // check if recording is implemented
  551.     gRecordingImplemented   = FeatureIsImplemented(gestaltAppleEventsAttr,1);
  552.         
  553.         // check for the Outline fonts
  554.     gOutlineFontsImplemented  = FeatureIsImplemented(gestaltFontMgrAttr, gestaltOutlineFonts);
  555.     
  556.         // We would also like the Drag Manager
  557.     gHasDragManager = FeatureIsImplemented ( gestaltDragMgrAttr, gestaltDragMgrPresent );
  558.  
  559. // It isn't enough to use Gestalt because we may not have sucessfully linked
  560. // to the DragLib shared library. So, we also need to test one of the symbols
  561. // against kUnresolvedSymbol to make sure we have a valid connection to it.
  562.  
  563. #if GENERATINGCFM
  564.     if ( gHasDragManager )
  565.         gHasDragManager = (InstallTrackingHandler != (void*) kUnresolvedSymbolAddress);
  566. #endif
  567.     
  568.         // Want the process manager
  569.     gHasProcessManager = ( noErr == Gestalt( gestaltOSAttr, &response ) );
  570.  
  571.  
  572.     return (gEditionManagerImplemented
  573.                 && gAliasManagerImplemented 
  574.                     && gAppleEventsImplemented
  575.                         && gOutlineFontsImplemented
  576.                             && gHasProcessManager );
  577.                             
  578. }  // CheckEnvironment
  579.             
  580.  
  581. //    DoPageSetup returns true if the page setup of the document is altered
  582.     
  583. Boolean    DoPageSetup(DPtr theDoc)
  584. {
  585.     Boolean result = false;
  586.     
  587.     if ( ! gGXIsPresent )
  588.         if ( theDoc )
  589.         {
  590.             PrOpen();
  591.             result =  PrStlDialog(theDoc->thePrintSetup);
  592.             PrClose();
  593.         }
  594.         
  595.     return(result);
  596. }  // DoPageSetup
  597.  
  598.  
  599. //    Name:    CtrlKeyPressed
  600. //    Purpose: Returns true if control key pressed during event
  601.  
  602. Boolean    CtrlKeyPressed( const EventRecord *theEvent )
  603. {
  604.     return((theEvent->modifiers & controlKey) != 0);
  605. }
  606.     
  607.  
  608. //    Name:    OptionKeyPressed
  609. //    Purpose: Returns true if option key pressed during event
  610.  
  611. Boolean    OptionKeyPressed( const EventRecord *theEvent )
  612. {
  613.     return((theEvent->modifiers & optionKey) != 0);
  614. }
  615.  
  616.  
  617. Boolean SetMenuItemState (  Boolean    theState,
  618.                             MenuHandle theMenu,
  619.                             short      item )
  620. {
  621.     Boolean reDrawMenuBar = false;
  622.     Boolean isSet;
  623.     
  624.     if (item == kMenuTitle)
  625.     {
  626.         isSet = ((*theMenu)->enableFlags & 0x00000001);
  627.         reDrawMenuBar = (isSet != theState);
  628.     }
  629.  
  630.     if (theState)
  631.         EnableItem ( theMenu, item );
  632.     else
  633.         DisableItem ( theMenu, item );
  634.     
  635.     return ( reDrawMenuBar );
  636. }
  637.